package com.zn.task;

import com.alibaba.fastjson.JSONObject;
import com.zn.entity.OptionTradingContract;
import com.zn.entity.OptionTradingGoods;
import com.zn.mapper.OptionAccountMapper;
import com.zn.mapper.OptionTradingContractMapper;
import com.zn.mapper.OptionTradingGoodsMapper;
import com.zn.service.OptionTradeService;
import com.zn.util.Constant;
import com.zn.util.DateUtils;
import com.zn.vo.OptionSymbol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author YinJiaWei
 * @version 2018/11/14 10:56
 * 风控强平定时任务
 */
@Component
public class RiskManagementCloseOrder {
    private static final Logger LOGGER = LoggerFactory.getLogger(RiskManagementCloseOrder.class);
    @Autowired
    private OptionTradingContractMapper optionTradingContractMapper;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private OptionTradeService optionTradeService;
    @Autowired
    private OptionAccountMapper optionAccountMapper;
    @Autowired
    private OptionTradingGoodsMapper optionTradingGoodsMapper;
    private ExecutorService pool = Executors.newCachedThreadPool();
    private Integer version=0;

    /**
     * 当日14点开始强平
     */
    @Scheduled(cron="0 00 14 * * ?")
    public void beginClosePosition() throws Exception{
        doClosePosition(1);
    }

    /**
     * 早上09.31分开始持续平仓
     */
    @Scheduled(cron="0 31 09 * * ?")
    public void continuedClosePosition() throws Exception{
        doClosePosition(2);
    }

    /**
     * 下午13.01分开始持续平仓
     */
    @Scheduled(cron="0 01 13 * * ?")
    public void continuedClosePositionT() throws Exception{
        doClosePosition(2);
    }

    /**
     * 早上8.30将昨天持仓已满和开仓已满的状态置为 未满
     */
    @Scheduled(cron="0 30 08 * * ?")
    public void updateOptionAccountIsFull(){
        optionAccountMapper.updateOptionAccountIsFull();
    }

//    /**
//     * 测试切换母账户
//     */
//    @Scheduled(cron="0 10 17 * * ?")
    public void test() throws Exception{
        /**report|交易日|报单提交状态|报单状态|报单编号|报单来源|报单类型|数量|最小成交量|今成交数量|报单价格|本地报单编号|合约|状态信息|报单时间|错误ID**/
        String respReportOne="report|20190123|3|3||0|0|1|1|0|0.0000|b190123100038|10001626|报单已提交|11:17:03|0|1|1|";
        /**模拟第二条报单全部成交报单已提交**/
        String respReportTwo="report|20190123|3|0|498576812|0|0|1|1|1|0.0001|b190123100038|10001626|全部成交报单已提交|11:17:03|0|1|1|";
        /**模拟第三条成交回报**/
        /**deal|开平方向|本地报单编号|合约code|报单编号|成交编号|成交日期|成交时间|手数|价格|买卖类型|交易类型**/
        String respDeal="deal|4|b190123100038|10001626|498576812|49857681213|20190123|11:17:03|1|0.0001|1|0";
        optionTradeService.respReportOrder(respReportOne);
        optionTradeService.respReportOrder(respReportTwo);
        optionTradeService.respDealOrder(respDeal);
    }


    /**
     *
     * @param type 1-开始风控平仓 2-持续风控平仓
     */
    private void doClosePosition(Integer type) throws Exception{
        pool.execute(new Thread(() -> {
            Object obj = redisTemplate.opsForValue().get(Constant.DATE_OF_TRANSACTION);
            List<OptionTradingGoods> optionTradingGoods = optionTradingGoodsMapper.findAll();
            /**循环10次**/
            while(true) {
                String msg = type == 1 ? "doClosePosition..............begin" : "doClosePosition..............continued";
                LOGGER.info(msg);
                String today = DateUtils.convertDateToString(new Date());
                OptionTradingContract optionTradingContractByWhere = new OptionTradingContract();
                optionTradingContractByWhere.setIsTrading(0);
                List<OptionTradingContract> optionTradingContractList = optionTradingContractMapper.selectByWhere(optionTradingContractByWhere);
                /**获取当前交易的月份**/
                for (OptionTradingContract optionTradingContract : optionTradingContractList) {
                    String itckKey = Constant.OPTION_TICKL_INFO + optionTradingContract.getTradingGoodsCode() + ":" + optionTradingContract.getContractMonthName() + ":" + today;
                    /**获取当前月份交易的合约**/
                    List<Object> tickList = redisTemplate.opsForHash().values(itckKey);
                    for (Object object : tickList) {
                        JSONObject jsonObject = JSONObject.parseObject(object.toString());
                        /**获取该合约code**/
                        String instrumentCode = jsonObject.getString("instrumentCode");
                        /**获取该合约距离交割天数**/
                        Object optionSymbol2Json=redisTemplate.opsForHash().get(Constant.OPTION_SYMBOL_INFO+today,instrumentCode);
                        OptionSymbol optionSymbol=JSONObject.parseObject(optionSymbol2Json.toString(), OptionSymbol.class);
                        Integer remainderDays = optionSymbol.getRemainderDays();//jsonObject.getInteger("remainderDays");
                        /**获取该月份到期提前天数**/
                        Integer forceCloseAdvanceDay = optionTradingContract.getForceCloseAdvanceDay();
                        /**如果交割距离天数等于提前天数 则开始强平**/
                        LOGGER.info("instrumentCode..........." + instrumentCode + ",remainderDays:.........." + remainderDays + ",forceCloseAdvanceDay.........." + forceCloseAdvanceDay);
                        Double limitPrice = jsonObject.getDouble("bidPrice1");
                        /**14:00开始风控平仓**/
                        if (type == 1 && remainderDays == forceCloseAdvanceDay) {
                            //                    LOGGER.info("doClosePosition..............begin"+optionTradingContract.getContractMonthName());
                            //申买价一
                            LOGGER.info("instrumentCode..........." + instrumentCode + ",remainderDays:.........." + remainderDays + ",forceCloseAdvanceDay.........." + forceCloseAdvanceDay +"doClosePositionBegin"+new Date());
                            optionTradeService.riskManagementClose(instrumentCode, limitPrice);
                        }
                        /**09:31持续风控平仓**/
                        if (type == 2 && remainderDays < forceCloseAdvanceDay && remainderDays > -1) {
                            //                    LOGGER.info("doClosePosition..............continued"+optionTradingContract.getContractMonthName());
                            LOGGER.info("instrumentCode..........." + instrumentCode + ",remainderDays:.........." + remainderDays + ",forceCloseAdvanceDay.........." + forceCloseAdvanceDay +"doClosePositionContinued"+new Date());
                            optionTradeService.riskManagementClose(instrumentCode, limitPrice);
                        }
                    }
                }
                /**判断是否是交易时间段，非交易时间段时退出当前轮询强平**/
                if (!DateUtils.EtfcheckTradeTime(obj.toString(), optionTradingGoods.get(0).getTradingTime())){
                    break;
                }
                /**停止3min**/
                try{Thread.sleep(180000);}catch (Exception e){}
            }
        }));
    }
}
